#include "stdafx.h"
#include "SingleInstance.h"

CSingleInstance::CSingleInstance(LPCTSTR pszUniqueName, int nCmdShow)
{
	m_hMap=NULL;
	m_pszUniqueName=NULL;

	//create unique name
	if (pszUniqueName)
	{
		int len=_tcslen(pszUniqueName)+_tcslen(TAG)+1;
		m_pszUniqueName=new TCHAR[len];

		if (m_pszUniqueName)
			_sntprintf(m_pszUniqueName, len, _T("%s%s"), pszUniqueName, TAG);
	}

	HWND hPrevWnd;
	//check if an instance is running
	if (GetPrevInstance(&hPrevWnd))
	{
		//check if the previous instance's main window is initialized and valid
		if (IsWindow(hPrevWnd))
		{
			ShowWindow(hPrevWnd, nCmdShow);
			BringWindowToTop(hPrevWnd);
			SetForegroundWindow(hPrevWnd);
		}
		else
			//previous instance started, yet main window not initilized
			MessageBox(NULL, _T("Only one instance is allowed"), _T("Error"), MB_OK);

		//stop execution
		ExitProcess(0);
	}
	else
		//no instance, create the file mapping with unique name
		CreateMap();
}

CSingleInstance::~CSingleInstance()
{
	//close file mapping
	if (m_hMap)
		CloseHandle(m_hMap);

	//free string
	if (m_pszUniqueName)
		delete m_pszUniqueName;
}

//store main window handle for later ones to active me
void CSingleInstance::SetWindow(HWND hWnd)
{
	if (m_hMap)
	{
		void *map=(void*)MapViewOfFile(m_hMap, FILE_MAP_WRITE, 0, 0, sizeof(HWND));
		if (map)
		{
			memcpy(map, &hWnd, sizeof(HWND));
			UnmapViewOfFile(map);
		}
	}
}

BOOL CSingleInstance::GetPrevInstance(HWND *phWnd)
{
	BOOL ret=FALSE;
	*phWnd=NULL;

	HANDLE hMap=OpenFileMapping(FILE_MAP_READ, FALSE, m_pszUniqueName?m_pszUniqueName:TAG);
	if (hMap)
	{
		ret=TRUE;

		void *map=(void*)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, sizeof(HWND));
		if (map)
		{
			memcpy(phWnd, map, sizeof(HWND));
			UnmapViewOfFile(map);
		}
		CloseHandle(hMap);
	}

	return ret;
}

//create file mapping
void CSingleInstance::CreateMap()
{
	m_hMap=CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, sizeof(HWND),
		m_pszUniqueName?m_pszUniqueName:TAG);
	if (m_hMap)
	{
		void *map=(void*)MapViewOfFile(m_hMap, FILE_MAP_WRITE, 0, 0, sizeof(HWND));
		if (map)
		{
			memset(map, 0, sizeof(HWND));
			UnmapViewOfFile(map);
		}
		else
		{
			CloseHandle(m_hMap);
			m_hMap=NULL;
		}
	}
}
